home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
mg2a_src.zip
/
DISPLAY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-16
|
24KB
|
885 lines
/*
* The functions in this file handle redisplay. The
* redisplay system knows almost nothing about the editing
* process; the editing functions do, however, set some
* hints to eliminate a lot of the grinding. There is more
* that can be done; the "vtputc" interface is a real
* pig. Two conditional compilation flags; the GOSLING
* flag enables dynamic programming redisplay, using the
* algorithm published by Jim Gosling in SIGOA. The MEMMAP
* changes things around for memory mapped video. With
* both off, the terminal is a VT52.
*/
#include "def.h"
#include "kbd.h"
/*
* You can change these back to the types
* implied by the name if you get tight for space. If you
* make both of them "int" you get better code on the VAX.
* They do nothing if this is not Gosling redisplay, except
* for change the size of a structure that isn't used.
* A bit of a cheat.
*/
/* These defines really belong in sysdef.h */
#ifndef XCHAR
# define XCHAR int
# define XSHORT int
#endif
#ifdef STANDOUT_GLITCH
extern int SG; /* number of standout glitches */
#endif
/*
* A video structure always holds
* an array of characters whose length is equal to
* the longest line possible. Only some of this is
* used if "ncol" isn't the same as "NCOL".
*/
typedef struct {
short v_hash; /* Hash code, for compares. */
short v_flag; /* Flag word. */
short v_color; /* Color of the line. */
XSHORT v_cost; /* Cost of display. */
char v_text[NCOL]; /* The actual characters. */
} VIDEO;
#define VFCHG 0x0001 /* Changed. */
#define VFHBAD 0x0002 /* Hash and cost are bad. */
#define VFEXT 0x0004 /* extended line (beond ncol) */
/*
* SCORE structures hold the optimal
* trace trajectory, and the cost of redisplay, when
* the dynamic programming redisplay code is used.
* If no fancy redisplay, this isn't used. The trace index
* fields can be "char", and the score a "short", but
* this makes the code worse on the VAX.
*/
typedef struct {
XCHAR s_itrace; /* "i" index for track back. */
XCHAR s_jtrace; /* "j" index for trace back. */
XSHORT s_cost; /* Display cost. */
} SCORE;
int sgarbf = TRUE; /* TRUE if screen is garbage. */
int vtrow = 0; /* Virtual cursor row. */
int vtcol = 0; /* Virtual cursor column. */
int tthue = CNONE; /* Current color. */
int ttrow = HUGE; /* Physical cursor row. */
int ttcol = HUGE; /* Physical cursor column. */
int tttop = HUGE; /* Top of scroll region. */
int ttbot = HUGE; /* Bottom of scroll region. */
int lbound = 0; /* leftmost bound of the current line */
/* being displayed */
VIDEO *vscreen[NROW-1]; /* Edge vector, virtual. */
VIDEO *pscreen[NROW-1]; /* Edge vector, physical. */
VIDEO video[2*(NROW-1)]; /* Actual screen data. */
VIDEO blanks; /* Blank line image. */
/*
* Some predeclerations to make ANSI compilers happy
*/
VOID vtinit();
VOID vttidy();
VOID vtmove();
VOID vtputc();
VOID vtpute();
VOID vteeol();
VOID update();
VOID updext();
VOID ucopy();
VOID uline();
VOID modeline();
VOID hash();
VOID setscores();
VOID traceback();
#ifdef GOSLING
/*
* This matrix is written as an array because
* we do funny things in the "setscores" routine, which
* is very compute intensive, to make the subscripts go away.
* It would be "SCORE score[NROW][NROW]" in old speak.
* Look at "setscores" to understand what is up.
*/
SCORE score[NROW*NROW];
#endif
/*
* Initialize the data structures used
* by the display code. The edge vectors used
* to access the screens are set up. The operating
* system's terminal I/O channel is set up. Fill the
* "blanks" array with ASCII blanks. The rest is done
* at compile time. The original window is marked
* as needing full update, and the physical screen
* is marked as garbage, so all the right stuff happens
* on the first call to redisplay.
*/
VOID
vtinit() {
register VIDEO *vp;
register int i;
ttopen();
ttinit();
vp = &video[0];
for (i=0; i<NROW-1; ++i) {
vscreen[i] = vp;
++vp;
pscreen[i] = vp;
++vp;
}
blanks.v_color = CTEXT;
for (i=0; i<NCOL; ++i)
blanks.v_text[i] = ' ';
}
/*
* Tidy up the virtual display system
* in anticipation of a return back to the host
* operating system. Right now all we do is position
* the cursor to the last line, erase the line, and
* close the terminal channel.
*/
VOID
vttidy() {
ttcolor(CTEXT);
ttnowindow(); /* No scroll window. */
ttmove(nrow-1, 0); /* Echo line. */
tteeol();
tttidy();
ttflush();
ttclose();
}
/*
* Move the virtual cursor to an origin
* 0 spot on the virtual display screen. I could
* store the column as a character pointer to the spot
* on the line, which would make "vtputc" a little bit
* more efficient. No checking for errors.
*/
VOID
vtmove(row, col) {
vtrow = row;
vtcol = col;
}
/*
* Write a character to the virtual display,
* dealing with long lines and the display of unprintable
* things like control characters. Also expand tabs every 8
* columns. This code only puts printing characters into
* the virtual display image. Special care must be taken when
* expanding tabs. On a screen whose width is not a multiple
* of 8, it is possible for the virtual cursor to hit the
* right margin before the next tab stop is reached. This
* makes the tab code loop if you are not careful.
* Three guesses how we found this.
*/
VOID
vtputc(c) register int c; {
register VIDEO *vp;
vp = vscreen[vtrow];
if (vtcol >= ncol)
vp->v_text[ncol-1] = '$';
else if (c == '\t'
#ifdef NOTAB
&& !(curbp->b_flag & BFNOTAB)
#endif
) {
do {
vtputc(' ');
} while (vtcol<ncol && (vtcol&0x07)!=0);
} else if (ISCTRL(c)) {
vtputc('^');
vtputc(CCHR(c));
} else
vp->v_text[vtcol++] = c;
}
/* Put a character to the virtual screen in an extended line. If we are
* not yet on left edge, don't print it yet. Check for overflow on
* the right margin.
*/
VOID
vtpute(c)
int c;
{
register VIDEO *vp;
vp = vscreen[vtrow];
if (vtcol >= ncol) vp->v_text[ncol - 1] = '$';
else if (c == '\t'
#ifdef NOTAB
&& !(curbp->b_flag & BFNOTAB)
#endif
) {
do {
vtpute(' ');
}
while (((vtcol + lbound)&0x07) != 0 && vtcol < ncol);
} else if (ISCTRL(c) != FALSE) {
vtpute('^');
vtpute(CCHR(c));
} else {
if (vtcol >= 0) vp->v_text[vtcol] = c;
++vtcol;
}
}
/* Erase from the end of the
* software cursor to the end of the
* line on which the software cursor is
* located. The display routines will decide
* if a hardware erase to end of line command
* should be used to display this.
*/
VOID
vteeol() {
register VIDEO *vp;
vp = vscreen[vtrow];
while (vtcol < ncol)
vp->v_text[vtcol++] = ' ';
}
/*
* Make sure that the display is
* right. This is a three part process. First,
* scan through all of the windows looking for dirty
* ones. Check the framing, and refresh the screen.
* Second, make sure that "currow" and "curcol" are
* correct for the current window. Third, make the
* virtual and physical screens the same.
*/
VOID
update() {
register LINE *lp;
register WINDOW *wp;
register VIDEO *vp1;
VIDEO *vp2;
register int i;
register int j;
register int c;
register int hflag;
register int currow;
register int curcol;
register int offs;
register int size;
VOID traceback ();
VOID uline ();
if (typeahead()) return;
if (sgarbf) { /* must update everything */
wp = wheadp;
while(wp != NULL) {
wp->w_flag |= WFMODE | WFHARD;
wp = wp->w_wndp;
}
}
hflag = FALSE; /* Not hard. */
wp = wheadp;
while (wp != NULL) {
if (wp->w_flag != 0) { /* Need update. */
if ((wp->w_flag&WFFORCE) == 0) {
lp = wp->w_linep;
for (i=0; i<wp->w_ntrows; ++i) {
if (lp == wp->w_dotp)
goto out;
if (lp == wp->w_bufp->b_linep)
break;
lp = lforw(lp);
}
}
i = wp->w_force; /* Reframe this one. */
if (i > 0) {
--i;
if (i >